from tkinter import Tk, Label, Button, filedialog, Text, Scrollbar, VERTICAL, END, DISABLED, NORMAL
from tkinter.ttk import Progressbar, Combobox
import os
import json
from pdf2image import convert_from_path
import re
import pandas as pd
from paddleocr import PaddleOCR

# 加载行政区划代码的 JSON 文件
with open('regions.json', 'r', encoding='utf-8') as file:
    region_codes = json.load(file)

# 创建 PaddleOCR 实例
ocr = PaddleOCR(use_angle_cls=True, lang='ch')  # 使用简体中文


# 提取图片中的文本
def extract_text_from_image(image_path):
    result = ocr.ocr(image_path, cls=True)
    text = ""
    for line in result:
        for word_info in line:
            text += word_info[1][0] + "\n"  # 提取文本内容
    return text.strip()


# 从文本中提取发票信息
def extract_invoice_info(text, file_name, invoice_type):
    if invoice_type == "004-增值税专用发票":
        invoice_code_match = re.search(r'(\d{10})', text)
        invoice_code = invoice_code_match.group(1) if invoice_code_match else None

        # 提取发票号码
        invoice_number_match = re.search(r'No[:：]?\s*(\d{8})', text)
        invoice_number = invoice_number_match.group(1) if invoice_number_match else None

        # 使用更宽松的正则表达式匹配日期
        invoice_date_match = re.search(r'(\d{4})\s*[年./-]\s*(\d{1,2})\s*[月./-]\s*(\d{1,2})', text)
        invoice_date = (
            f"{invoice_date_match.group(1)}/{invoice_date_match.group(2).zfill(2)}/{invoice_date_match.group(3).zfill(2)}"
            if invoice_date_match else None
        )

        # 查找所有包含“￥”或“¥”符号的金额，并排序取第二大
        amounts = re.findall(r'[￥¥](\d+\.\d+)', text)
        amounts = sorted([float(amount) for amount in amounts], reverse=True)
        invoice_amount = amounts[1] if len(amounts) > 1 else (amounts[0] if amounts else None)

        # 发票类型动态传递
        invoice_type = invoice_type if invoice_type else '未知类型'

        # 检查发票代码是否符合要求：长度为10且前四位在region_codes中
        if invoice_code and len(invoice_code) == 10 and invoice_code[:4] in region_codes:
            region_name = region_codes[invoice_code[:4]]
        else:
            region_name = None  # 不符合条件时返回None
    elif invoice_type == "005-机动车销售统一发票":
        return None
    elif invoice_type == "007-增值税普通发票":
        return None
    elif invoice_type == "026-增值税电子普通发票":
        invoice_code_match = re.search(r'发票代码[:：]?\s*(\d{12})', text)
        invoice_code = invoice_code_match.group(1) if invoice_code_match else None

        # 提取发票号码
        invoice_number_match = re.search(r'发票号码[:：]?\s*(\d{8})', text)
        invoice_number = invoice_number_match.group(1) if invoice_number_match else None

        # 使用更宽松的正则表达式匹配日期
        invoice_date_match = re.search(r'(\d{4})\s*[年./-]\s*(\d{1,2})\s*[月./-]\s*(\d{1,2})', text)
        invoice_date = (
            f"{invoice_date_match.group(1)}/{invoice_date_match.group(2).zfill(2)}/{invoice_date_match.group(3).zfill(2)}"
            if invoice_date_match else None
        )

        # 查找所有包含“￥”或“¥”符号的金额，并排序取第二大
        amounts = re.findall(r'[￥¥](\d+\.\d+)', text)
        amounts = sorted([float(amount) for amount in amounts], reverse=True)
        invoice_amount = amounts[1] if len(amounts) > 1 else (amounts[0] if amounts else None)

        # 发票类型动态传递
        invoice_type = invoice_type if invoice_type else '未知类型'

        # 检查发票代码是否符合要求
        if invoice_code and len(invoice_code) == 12 and invoice_code[1:5] in region_codes:
            region_name = region_codes[invoice_code[1:5]]
        else:
            region_name = None  # 不符合条件时返回None
    elif invoice_type == "025-增值税普通发票（卷式）":
        return None
    elif invoice_type == "14-增值税电子普通发票（通行费）":
        return None
    elif invoice_type == "06-二手车发票":
        return None
    elif invoice_type == "028-增值税电子专用发票":
        return None
    elif invoice_type == "31-数电发票（增值税电子专用发票）":
        invoice_code = None

        # 提取发票号码
        invoice_number_match = re.search(r'发票号码[:：]?\s*(\d{20})', text)
        invoice_number = invoice_number_match.group(1) if invoice_number_match else None

        # 使用更宽松的正则表达式匹配日期
        invoice_date_match = re.search(r'(\d{4})\s*[年./-]\s*(\d{1,2})\s*[月./-]\s*(\d{1,2})', text)
        invoice_date = (
            f"{invoice_date_match.group(1)}/{invoice_date_match.group(2).zfill(2)}/{invoice_date_match.group(3).zfill(2)}"
            if invoice_date_match else None
        )

        # 查找所有包含“￥”或“¥”符号的金额，并排序取第二大
        amounts = re.findall(r'[￥¥](\d+\.\d+)', text)
        amounts = sorted([float(amount) for amount in amounts], reverse=True)
        invoice_amount = amounts[0]

        # 发票类型动态传递
        invoice_type = invoice_type if invoice_type else '未知类型'

        region_name = None
        # # 检查发票代码是否符合要求
        # if invoice_code and len(invoice_code) == 12 and invoice_code[1:5] in region_codes:
        #     region_name = region_codes[invoice_code[1:5]]
        # else:
        #     region_name = None  # 不符合条件时返回None
    elif invoice_type == "32-数电发票（增值税电子普通发票）":
        return None
    return (
        invoice_code,
        invoice_number,
        invoice_date,
        invoice_type,
        invoice_amount,
        region_name
    )


# 处理 PDF，转换为图片并提取信息
def process_pdf(pdf_path, file_name, invoice_type):
    images = convert_from_path(pdf_path)
    for image in images:
        # 保存图片到临时文件，以便 PaddleOCR 读取
        temp_image_path = "temp_image.png"
        image.save(temp_image_path, "PNG")
        text = extract_text_from_image(temp_image_path)
        print(text)
        return extract_invoice_info(text, file_name, invoice_type)


# 遍历文件夹及其子文件夹中的所有PDF文件
def traverse_folders(folder_path, progress_bar, log_text, invoice_type):
    data = []
    pdf_files = []

    # 使用 os.walk() 递归遍历所有子文件夹
    for root, dirs, files in os.walk(folder_path):
        for file in files:
            if file.endswith('.pdf'):
                pdf_files.append(os.path.join(root, file))

    total_files = len(pdf_files)
    progress_step = 100 / total_files if total_files else 0

    # 处理每个 PDF 文件并更新进度条
    for i, pdf_path in enumerate(pdf_files):
        file_name = os.path.basename(pdf_path)

        # 将路径分隔符统一为 "/"
        formatted_path = pdf_path.replace("\\", "/")

        # 更新日志内容
        log_text.config(state=NORMAL)  # 设置为可写入
        log_text.insert(END, f"{formatted_path}\n")  # 显示当前文件路径
        log_text.config(state=DISABLED)  # 设置为只读
        log_text.see(END)  # 滚动到最新消息

        invoice_data = process_pdf(pdf_path, file_name, invoice_type)
        data.append(invoice_data)
        progress_bar['value'] += progress_step
        progress_bar.update()

    # 显示处理完成的提示
    log_text.config(state=NORMAL)
    log_text.insert(END, f"============================================================\n")
    log_text.insert(END, f"已提取完所有文件，共{total_files}个文件\n")
    log_text.config(state=DISABLED)
    log_text.see(END)  # 滚动到最新消息
    return data


# 保存信息为 Excel 文件
def save_to_excel(data, folder_path, invoice_type):
    # # 创建一个目录来保存对应的文件
    # invoice_type_folder = os.path.join(folder_path, "税票信息汇总")
    # os.makedirs(invoice_type_folder, exist_ok=True)  # 创建文件夹（如果不存在的话）
    df = pd.DataFrame(data, columns=['发票代码', '发票号码', '开票日期yyyy/MM/dd', '发票类型', '发票金额（不含税）', '所属地区'])
    # 根据发票类型命名文件
    output_path = os.path.join(folder_path, f"{invoice_type}.xlsx").replace("\\", "/")
    # output_path = os.path.join(invoice_type_folder, f"{invoice_type}.xlsx").replace("\\", "/")
    # output_path = os.path.join(invoice_type_folder, f"{invoice_type}.xlsx")
    df.to_excel(output_path, index=False)
    return output_path


# 选择文件夹并开始处理
def select_folder():
    folder_path = filedialog.askdirectory()
    if not folder_path:
        return

    invoice_type = invoice_type_combobox.get()  # 获取用户选择的发票类型

    progress_bar['value'] = 0  # 重置进度条
    log_text.config(state=NORMAL)
    log_text.delete(1.0, END)  # 清空日志窗口
    log_text.insert(END, "开始提取发票信息，请稍等...\n")
    log_text.insert(END, "=======================正在提取文件=========================\n")
    log_text.config(state=DISABLED)
    invoice_data = traverse_folders(folder_path, progress_bar, log_text, invoice_type)

    if not invoice_data:
        log_text.config(state=NORMAL)
        log_text.insert(END, "未找到任何 PDF 文件！\n")
        log_text.config(state=DISABLED)
        return

    output_path = save_to_excel(invoice_data, folder_path, invoice_type)
    log_text.config(state=NORMAL)
    log_text.insert(END, f"税票信息已保存至 {output_path}！\n")
    log_text.config(state=DISABLED)


# 创建主界面
root = Tk()
root.title("发票信息提取器")
root.geometry("500x450")

Label(root, text="发票信息提取工具", font=("Arial", 16)).pack(pady=10)

# 添加发票类型选择
Label(root, text="选择发票类型", font=("Arial", 12)).pack(pady=5)
invoice_type_combobox = Combobox(root, values=["004-增值税专用发票", "005-机动车销售统一发票", "007-增值税普通发票", "026-增值税电子普通发票", "025-增值税普通发票（卷式）", "14-增值税电子普通发票（通行费）", "06-二手车发票", "028-增值税电子专用发票", "31-数电发票（增值税电子专用发票）", "32-数电发票（增值税电子普通发票）"], state="readonly", font=("Arial", 12))
invoice_type_combobox.set("004-增值税专用发票")  # 默认选择项
invoice_type_combobox.pack(pady=10)

Button(root, text="选择文件夹并处理", command=select_folder, font=("Arial", 12)).pack(pady=10)

progress_bar = Progressbar(root, orient='horizontal', length=400, mode='determinate')
progress_bar.pack(pady=10)

# 添加滚动条和日志文本框
log_text = Text(root, wrap='word', width=60, height=10, state=DISABLED)
log_text.pack(pady=10)

scrollbar = Scrollbar(root, orient=VERTICAL, command=log_text.yview)
log_text.configure(yscrollcommand=scrollbar.set)
scrollbar.pack(side="right", fill="y")

root.mainloop()
